package com.hsyt.pms.security;


import com.hsyt.pms.security.rsa.util.RSAEncrypt;
import com.hsyt.pms.security.rsa.RsaKeyPairQueue;
import com.hsyt.pms.security.rsa.util.RsaKeyPair;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName: YtLoginAuthenticationFilter
 * @Description: 登录请求处理
 * @author 王勇琳
 * @date 2017年6月29日 下午6:33:42
 */
public class YtLoginAuthenticationFilter extends YtAbstractAuthenticationProcessingFilter {

	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
	public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";

	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
	private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
	private boolean postOnly = true;
	
	private RsaKeyPairQueue rsaKeyPairQueue;

	public YtLoginAuthenticationFilter() {
		super(new AntPathRequestMatcher("/login", "POST"));
	}

	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("不支持" + request.getMethod()+"认证请求方法！");
		}
		
		//TODO 用户名的分发校验
		//TODO 用户密码的解密及基础校验
		//TODO 其他参数的校验处理
		
		String username = obtainUsername(request);
		String password = obtainPassword(request);

		if (StringUtils.isBlank(username)) {
			throw new AuthenticationServiceException("用户名不能为空！");
		}
		if (StringUtils.isBlank(password)) {
			throw new AuthenticationServiceException("密码不能为空！");
		}


		try {
			// 到秘钥的队列中获取秘钥
			RsaKeyPair keyPair = rsaKeyPairQueue.takeQueue(request);
			if(keyPair==null || StringUtils.isBlank(keyPair.getPrivateKey())){
				logger.error("登录提交认证时，rsa公私钥队列相关操作异常，keyPair="+keyPair);
				throw new AuthenticationServiceException("登录异常！");
			}
			// 获取私钥
			String privateKey = keyPair.getPrivateKey();
			// 解密密码
			password = RSAEncrypt.decryptByPrivateKeyStr(privateKey, password);
//		   password = "2c5b2d714bef9ac49fc7382368f9f9569da021afa81a16b07619be7563b0abd576e749f3abdd2cb1";
//		   username = "super";
		} catch (InterruptedException e) {
			logger.error("登录提交认证时，rsa公私钥队列相关操作异常", e);
			throw new AuthenticationServiceException("登录异常！");
		} catch (Exception e) {
			logger.error("登录提交认证时，可能rsa解密异常", e);
			throw new AuthenticationServiceException("登录异常！");
		}
		  // 用户加上token
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
         //  存放session
		setDetails(request, authRequest);
		//   获取权限
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	protected String obtainPassword(HttpServletRequest request) {
		return request.getParameter(passwordParameter);
	}

	protected String obtainUsername(HttpServletRequest request) {
		return request.getParameter(usernameParameter);
	}

	protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

	public void setUsernameParameter(String usernameParameter) {
		Assert.hasText(usernameParameter, "用户名不能为空！");
		this.usernameParameter = usernameParameter;
	}

	public void setPasswordParameter(String passwordParameter) {
		Assert.hasText(passwordParameter, "密码不能为空！");
		this.passwordParameter = passwordParameter;
	}

	public void setPostOnly(boolean postOnly) {
		this.postOnly = postOnly;
	}

	public final String getUsernameParameter() {
		return usernameParameter;
	}

	public final String getPasswordParameter() {
		return passwordParameter;
	}

	public void setRsaKeyPairQueue(RsaKeyPairQueue rsaKeyPairQueue) {
		this.rsaKeyPairQueue = rsaKeyPairQueue;
	}
	
}
